package client.comm.baoding.ui.vm

import android.app.Application
import android.net.Uri
import androidx.databinding.ObservableField
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import androidx.paging.*
import client.comm.commlib.network.data.JsonResult
import client.comm.commlib.network.data.Ret
import client.comm.commlib.out_time
import client.comm.commlib.toast.toast
import client.comm.commlib.utils.StoreUtil
import client.comm.commlib.utils.Util
import client.comm.baoding.api.bean.*
import client.comm.baoding.ui.viewmodel.MiddleVm

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.Response
import java.lang.Exception

class MainViewModel(app: Application) : MiddleVm(app) {

    val isShowing = MutableLiveData<Boolean>(false)

    val userAvatar = MutableLiveData<Uri>()
    val callUser = MutableLiveData<JsonResult<UserInfo>>()

    val isCheckAll = MutableLiveData<Boolean>(false)
    val isEditMode = MutableLiveData<String>("编辑")
    val isEditModeVal = MutableLiveData<Boolean>(true)

    val callBuyCart = MutableLiveData<JsonResult<BuyCartRet>>()
    val delRet = MutableLiveData<JsonResult<Ret>>()

    val cateId = MutableLiveData<String>("")
    val cateId2 = MutableLiveData<String>("")
    val homeCall = MutableLiveData<JsonResult<GoodsIndex>>()
    val home2Call = MutableLiveData<JsonResult<GoodsIndex>>()

    val cutTab = MutableLiveData<String>("0")
    val cutTab2 = MutableLiveData<String>("0")
    val isCateLoading = MutableLiveData<Boolean>(false)
    val isCate2Loading = MutableLiveData<Boolean>(false)
    val isOneLoading = MutableLiveData<Boolean>(false)

    val isCateNewLoading = MutableLiveData<Boolean>(false)

    val callCate = MutableLiveData<JsonResult<CateGoods>>()
    val callCate2 = MutableLiveData<JsonResult<CateGoods>>()
    val callCateNew = MutableLiveData<JsonResult<CateGoods>>()
    val callTd = MutableLiveData<JsonResult<UserInfo>>()
    val rechargeOrder = MutableLiveData<JsonResult<CurrentRechargeOrder>>()

    val switchValue = MutableLiveData<Int>(-1)
    val pageOne = MutableLiveData<Int>(0)
    val pageCateNew = MutableLiveData<Int>(0)

    val callOne = MutableLiveData<JsonResult<TdBean>>()
    val startCall = MutableLiveData<JsonResult<Ret>>()
    val isSign = MutableLiveData<Boolean>(false)

    val userId = MutableLiveData<String>()

    val isLoadMore = MutableLiveData<Boolean>(false)

    //getOrder
    fun getRechargeOrder() {
        hold({
            server.current_recharge()
        }, {
            isShowing.value = true
        }, success = {
            rechargeOrder.value = it
        }, complete = {
            isShowing.value = false
        })
    }

    fun get_user_team() {
        if (isOneLoading.value!!)
            return
        hold({
            server.get_user_team(userId.value!!, pageOne.value!!)
        }, {
            isOneLoading.value = true
            pageOne.value = pageOne.value!! + 1
        }, {
            callOne.value = it
        }, complete = {
            isOneLoading.value = false
        })
    }

    fun pagingDataUser(): Flow<PagingData<GoodsIndex.TjGoods>> {
        return Pager(
            config = PagingConfig(pageSize = 10),
            pagingSourceFactory = {
                object : PagingSource<Int, GoodsIndex.TjGoods>() {
                    override fun getRefreshKey(state: PagingState<Int, GoodsIndex.TjGoods>): Int? =
                        null

                    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, GoodsIndex.TjGoods> {
                        return try {
                            val page = params.key ?: 1
                            val ret = server.goods_index_p(page)
                            if (ret.body() != null && ret.body()!!.isSuccess) {
                                val list = ret.body()!!.data!!.tj_goods_list
                                val pPage = if (page > 1) page - 1 else null
                                val nextKey = if (list.size >= 10) page + 1 else null
                                homeCall.value = ret.body()
                                LoadResult.Page(list, pPage, nextKey)
                            } else
                                LoadResult.Error(Exception("网络错误"))
                        } catch (e: Exception) {
                            LoadResult.Error(e)
                        }
                    }
                }
            }
        ).flow
    }

    fun pagingDataUser2(): Flow<PagingData<GoodsIndex.TjGoods>> {
        return Pager(
            config = PagingConfig(pageSize = 20),
            pagingSourceFactory = {
                object : PagingSource<Int, GoodsIndex.TjGoods>() {
                    override fun getRefreshKey(state: PagingState<Int, GoodsIndex.TjGoods>): Int? =
                        null

                    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, GoodsIndex.TjGoods> {
                        return try {
                            val page = params.key ?: 1
                            val ret = server.goods_index()
                            if (ret.body() != null && ret.body()!!.isSuccess) {
                                val list = ret.body()!!.data!!.tj_goods_list
                                val pPage = if (page > 1) page - 1 else null
                                val nextKey = if (list.size >= 20) page + 1 else null
                                home2Call.value = ret.body()
                                LoadResult.Page(list, pPage, nextKey)
                            } else
                                LoadResult.Error(Exception("网络错误"))
                        } catch (e: Exception) {
                            LoadResult.Error(e)
                        }
                    }
                }
            }
        ).flow
    }

    fun cateChildFlow(cate: String): Flow<PagingData<CateGoods.Goods>> =
        Pager<Int, CateGoods.Goods>(
            config = PagingConfig(pageSize = 200),
            pagingSourceFactory = {
                object : PagingSource<Int, CateGoods.Goods>() {
                    override fun getRefreshKey(state: PagingState<Int, CateGoods.Goods>): Int? =
                        null

                    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CateGoods.Goods> {
                        return try {
                            val page = params.key ?: 1
                            val ret = server.goods_type_detail(page, cate)
                            if (ret.body() != null && ret.body()!!.isSuccess) {
                                val list = ret.body()!!.data!!.goods_list
                                val pPage = if (page > 1) page - 1 else null
                                val nextKey = if (list.size >= 20) page + 1 else null
                                LoadResult.Page(list, pPage, nextKey)
                            } else
                                LoadResult.Error(Exception("网络错误"))
                        } catch (e: Exception) {
                            LoadResult.Error(e)
                        }
                    }
                }
            }
        ).flow

    fun cateChild2Flow(cate: String): Flow<PagingData<CateGoods.Goods>> =
        Pager<Int, CateGoods.Goods>(
            config = PagingConfig(pageSize = 200),
            pagingSourceFactory = {
                object : PagingSource<Int, CateGoods.Goods>() {
                    override fun getRefreshKey(state: PagingState<Int, CateGoods.Goods>): Int? =
                        null

                    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CateGoods.Goods> {
                        return try {
                            val page = params.key ?: 1
                            val ret = server.goods_type_detail(page, cate)
                            if (ret.body() != null && ret.body()!!.isSuccess) {
                                val list = ret.body()!!.data!!.goods_list
                                val pPage = if (page > 1) page - 1 else null
                                val nextKey = if (list.size >= 20) page + 1 else null
                                LoadResult.Page(list, pPage, nextKey)
                            } else
                                LoadResult.Error(Exception("网络错误"))
                        } catch (e: Exception) {
                            LoadResult.Error(e)
                        }
                    }
                }
            }
        ).flow


    fun homeOne() {
        hold({
            server.goods_index()
        }, {
        }, {
            homeCall.value = it
        })
    }


    fun holdCateNew(cate: String) {
        hold({
            server.goods_type_detail(pageCateNew.value!!, cate)
        }, {
            isCateNewLoading.value = true
            pageCateNew.value = pageCateNew.value!! + 1
        }, {
            callCateNew.value = it
        }, complete = {
            isCateNewLoading.value = false
        })

    }

    fun holdCateChild(
        cate: String,
        page: Int,
        callCate: MutableLiveData<JsonResult<CateGoods>>,
        isLoading: MutableLiveData<Boolean>
    ) {
        hold({
            server.goods_type_detail(page, cate)
        }, {
            isLoading.value = true
        }, {
            callCate.value = it
        }, complete = {
            isLoading.value = false
        })
    }

    /**
     * 首页分类
     */
    fun holdCate() {
        if (isCateLoading.value!!)
            return
        hold({
            server.goods_type_detail(1, "0")
        }, {
            isCateLoading.value = true
        }, {
            callCate.value = it
        }, complete = {
            isCateLoading.value = false
        })
    }

    /**
     * 优选分类
     */
    fun holdCate2() {
        if (isCate2Loading.value!!)
            return
        hold({
            server.goods_type_detail2(1, "0")
        }, {
            isCate2Loading.value = true
        }, {
            callCate2.value = it
        }, complete = {
            isCate2Loading.value = false
        })
    }


    fun buyCart(): Flow<PagingData<BuyCartRet.Shopping>> = Pager<Int, BuyCartRet.Shopping>(
        config = PagingConfig(pageSize = 20),
        pagingSourceFactory = {
            object : PagingSource<Int, BuyCartRet.Shopping>() {
                override fun getRefreshKey(state: PagingState<Int, BuyCartRet.Shopping>): Int? =
                    null

                override suspend fun load(params: LoadParams<Int>): LoadResult<Int, BuyCartRet.Shopping> {
                    return try {
                        val page = params.key ?: 1
                        val ret = server.shopping_cart()
                        if (ret.body() != null && ret.body()!!.isSuccess) {
                            val list = ret.body()!!.data!!.shopping_list

                            for (i in list) {
                                i.selectNum = ObservableField("${i.num}")
                                i.isCheck = ObservableField<Boolean>(false)
                            }
                            val pPage = if (page > 1) page - 1 else null
                            val nextKey = if (list.size >= 20) page + 1 else null
                            LoadResult.Page(list, pPage, nextKey)
                        } else
                            LoadResult.Error(Exception("网络错误"))
                    } catch (e: Exception) {
                        LoadResult.Error(e)
                    }
                }
            }
        }
    ).flow


    fun delCart(list: ArrayList<BuyCartRet.Shopping>) {
        hold({
            var goods_sku_idS = ""
            for (i in list) {
                goods_sku_idS += "${i.shopping_id},"
            }
            server.del_shopping_cart(goods_sku_idS)
        }, {
            isShowing.value = true
        }, {
            delRet.value = it
        }, complete = {
            isShowing.value = false
        })
    }

    fun start() {
        isShowing.value = true
        isSign.value = true
        hold({
            server.user_sign_in()
        }, success = {
            startCall.value = it
        }, complete = {
            isShowing.value = false
        }, err = {
            isSign.value = false
        })
    }

    fun setAvatar(lo: LifecycleOwner) {
        if (userAvatar.value == null) {
            toast("请选择图片")
            return
        }
        isShowing.value = true
        viewModelScope.launch {
            flow {
                var emm: Response<JsonResult<UploadRet>>? = null
                val file = Util.getLuBan(
                    lo,
                    userAvatar.value!!
                )
                val requestFile: RequestBody = RequestBody.create(
                    "multipart/form-data".toMediaTypeOrNull(),
                    file
                )
                val body = MultipartBody.Part.createFormData(
                    "file",
                    file.name,
                    requestFile
                )
                val descriptionString = "file"
                val description = RequestBody.create(
                    "multipart/form-data".toMediaTypeOrNull(),
                    descriptionString
                )
                out_time {
                    val ret = server.upload(description, body)
                    emm = ret
                }
                emit(emm)
            }.map {
                var emm: JsonResult<Ret>? = null
                it?.body()?.let {
                    if (it.isSuccess) {
                        out_time {
                            val ret = server.user_avatar(it.data!!.url)
                            emm = ret?.body()
                        }
                    } else {
                        emm = JsonResult<Ret>().apply {
                            message = it.message
                        }
                    }
                }
                emm
            }.flowOn(Dispatchers.IO).onCompletion { cause ->
                isShowing.value = false
            }.catch { cause ->
                if (cause != null) {
//                    toast(cause.message)
                    toast("网络错误")
                }
            }.collectLatest {
                it?.let {
                    if (it.isSuccess) {
                        toast("设置成功")
                        userInfo()
                    } else {
                        toast(it.message)
                    }
                }
            }
        }
    }

    fun userInfo() {
        hold({
            server.userinfo().apply {
                body()?.let {
                    if (it.isSuccess) {
                        StoreUtil.saveBean(getApplication(), it.data!!)
                    }
                }
            }
        }, success = {
            callUser.value = it
            callTd.value = it
        })
    }

    fun userSignIn() {

    }
}